package com.googlecode.perfectable.persistable.storage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.googlecode.perfectable.persistable.serialization.ObjectSerializer;
import com.googlecode.perfectable.persistable.serialization.Separator;
import com.googlecode.perfectable.persistable.session.Identifier;

public abstract class AbstractSerializingStorage extends AbstractStorage {

	protected final ObjectSerializer serializer;

	protected abstract InputStream inputStream(Identifier<?> identity);

	protected abstract OutputStream outputStream(Identifier<?> identity);

	protected AbstractSerializingStorage() {
		this.serializer = new ObjectSerializer(this);
	}

	protected AbstractSerializingStorage(Separator separator) {
		this.serializer = new ObjectSerializer(this, separator);
	}

	protected AbstractSerializingStorage(Separator separator, Persister relationPersister) {
		this.serializer = new ObjectSerializer(this, relationPersister, separator);
	}

	public void setRelationPersister(Persister relationPersister) {
		this.serializer.setPersister(relationPersister);
	}

	@Override
	public <T> void doPersist(T entity, Identifier<? super T> identity) {
		try(OutputStream sink = outputStream(identity)) {
			this.serializer.write(sink, entity);
		}
		catch(IOException e) {
			throw new RuntimeException(e); // TODO Auto-generated catch block
		}
	}

	@Override
	public <T> T materialize(Identifier<T> identity) {
		try(InputStream source = inputStream(identity)) {
			return (T) this.serializer.read(source); // MARK cast
		}
		catch(IOException | ClassNotFoundException e) {
			throw new RuntimeException(e); // TODO Auto-generated catch block
		}
	}

}
